#include "libyuv_test.h"

#ifdef __cplusplus
namespace libyuv {
    extern "C" {
#endif

    JNIEXPORT void JNICALL
    Java_com_andova_libyuv_LibYUV_00024Companion_TestAndroid420ToI420(JNIEnv *env, jobject,
                                                                      jbyteArray src_y, jbyteArray src_u, jbyteArray src_v,
                                                                      jbyteArray dst_y, jbyteArray dst_u, jbyteArray dst_v,
                                                                      jint width, jint height) {
        jbyte *y_src = env->GetByteArrayElements(src_y, nullptr);
        jbyte *u_src = env->GetByteArrayElements(src_u, nullptr);
        jbyte *v_src = env->GetByteArrayElements(src_v, nullptr);
        jbyte *y_dst = env->GetByteArrayElements(dst_y, nullptr);
        jbyte *u_dst = env->GetByteArrayElements(dst_u, nullptr);
        jbyte *v_dst = env->GetByteArrayElements(dst_v, nullptr);

        libyuv::Android420ToI420(
                (const uint8_t *) y_src, width,
                (const uint8_t *) u_src, (width + 1) / 2,
                (const uint8_t *) v_src, (width + 1) / 2,
                1,
                (uint8_t *) y_dst, width,
                (uint8_t *) u_dst, (width + 1) / 2,
                (uint8_t *) v_dst, (width + 1) / 2,
                width, height
        );

        env->ReleaseByteArrayElements(src_y, y_src, 0);
        env->ReleaseByteArrayElements(src_u, u_src, 0);
        env->ReleaseByteArrayElements(src_v, v_src, 0);
        env->ReleaseByteArrayElements(dst_y, y_dst, 0);
        env->ReleaseByteArrayElements(dst_u, u_dst, 0);
        env->ReleaseByteArrayElements(dst_v, v_dst, 0);
    }

    JNIEXPORT void JNICALL
    Java_com_andova_libyuv_LibYUV_00024Companion_TestI422ToI420(JNIEnv *env, jobject,
                                                                jbyteArray src_y, jbyteArray src_u, jbyteArray src_v,
                                                                jbyteArray dst_y, jbyteArray dst_u, jbyteArray dst_v,
                                                                jint width, jint height) {
        jbyte *y_src = env->GetByteArrayElements(src_y, nullptr);
        jbyte *u_src = env->GetByteArrayElements(src_u, nullptr);
        jbyte *v_src = env->GetByteArrayElements(src_v, nullptr);
        jbyte *y_dst = env->GetByteArrayElements(dst_y, nullptr);
        jbyte *u_dst = env->GetByteArrayElements(dst_u, nullptr);
        jbyte *v_dst = env->GetByteArrayElements(dst_v, nullptr);

        libyuv::I422ToI420(
                (const uint8_t *) y_src, width,
                (const uint8_t *) u_src, (width + 1) / 2,
                (const uint8_t *) v_src, (width + 1) / 2,
                (uint8_t *) y_dst, width,
                (uint8_t *) u_dst, (width + 1) / 2,
                (uint8_t *) v_dst, (width + 1) / 2,
                width, height
        );

        env->ReleaseByteArrayElements(src_y, y_src, 0);
        env->ReleaseByteArrayElements(src_u, u_src, 0);
        env->ReleaseByteArrayElements(src_v, v_src, 0);
        env->ReleaseByteArrayElements(dst_y, y_dst, 0);
        env->ReleaseByteArrayElements(dst_u, u_dst, 0);
        env->ReleaseByteArrayElements(dst_v, v_dst, 0);
    }

    JNIEXPORT void JNICALL
    Java_com_andova_libyuv_LibYUV_00024Companion_TestI444ToI420(JNIEnv *env, jobject,
                                                                jbyteArray src_y, jbyteArray src_u, jbyteArray src_v,
                                                                jbyteArray dst_y, jbyteArray dst_u, jbyteArray dst_v,
                                                                jint width, jint height) {
        jbyte *y_src = env->GetByteArrayElements(src_y, nullptr);
        jbyte *u_src = env->GetByteArrayElements(src_u, nullptr);
        jbyte *v_src = env->GetByteArrayElements(src_v, nullptr);
        jbyte *y_dst = env->GetByteArrayElements(dst_y, nullptr);
        jbyte *u_dst = env->GetByteArrayElements(dst_u, nullptr);
        jbyte *v_dst = env->GetByteArrayElements(dst_v, nullptr);

        libyuv::I444ToI420(
                (const uint8_t *) y_src, width,
                (const uint8_t *) u_src, (width + 1) / 2,
                (const uint8_t *) v_src, (width + 1) / 2,
                (uint8_t *) y_dst, width,
                (uint8_t *) u_dst, (width + 1) / 2,
                (uint8_t *) v_dst, (width + 1) / 2,
                width, height
        );

        env->ReleaseByteArrayElements(src_y, y_src, 0);
        env->ReleaseByteArrayElements(src_u, u_src, 0);
        env->ReleaseByteArrayElements(src_v, v_src, 0);
        env->ReleaseByteArrayElements(dst_y, y_dst, 0);
        env->ReleaseByteArrayElements(dst_u, u_dst, 0);
        env->ReleaseByteArrayElements(dst_v, v_dst, 0);
    }

    JNIEXPORT void JNICALL
    Java_com_andova_libyuv_LibYUV_00024Companion_TestI420ToNV21(JNIEnv *env, jobject,
                                                                jbyteArray src_y, jbyteArray src_u, jbyteArray src_v,
                                                                jbyteArray dst_yuv, jint width, jint height) {
        jbyte *y_src = env->GetByteArrayElements(src_y, nullptr);
        jbyte *u_src = env->GetByteArrayElements(src_u, nullptr);
        jbyte *v_src = env->GetByteArrayElements(src_v, nullptr);
        jbyte *yuv_dst = env->GetByteArrayElements(dst_yuv, nullptr);

        libyuv::I420ToNV21(
                (const uint8_t *) y_src, width,
                (const uint8_t *) u_src, (width + 1) / 2,
                (const uint8_t *) v_src, (width + 1) / 2,
                (uint8_t *) yuv_dst, width,
                (uint8_t *) yuv_dst + width * height, width,
                width, height
        );

        env->ReleaseByteArrayElements(src_y, y_src, 0);
        env->ReleaseByteArrayElements(src_u, u_src, 0);
        env->ReleaseByteArrayElements(src_v, v_src, 0);
        env->ReleaseByteArrayElements(dst_yuv, yuv_dst, 0);
    }

    JNIEXPORT void JNICALL
    Java_com_andova_libyuv_LibYUV_00024Companion_TestNV21ToI420(JNIEnv *env, jobject,
                                                                jbyteArray src_y, jbyteArray dst_y, jbyteArray dst_u, jbyteArray dst_v,
                                                                jint width, jint height) {

        jbyte *y_src = env->GetByteArrayElements(src_y, nullptr);
        jbyte *y_dst = env->GetByteArrayElements(dst_y, nullptr);
        jbyte *u_dst = env->GetByteArrayElements(dst_u, nullptr);
        jbyte *v_dst = env->GetByteArrayElements(dst_v, nullptr);

        libyuv::NV21ToI420(
                (const uint8_t *) y_src, width,
                (const uint8_t *) y_src + width * height, width,
                (uint8_t *) y_dst, width,
                (uint8_t *) u_dst, (width + 1) / 2,
                (uint8_t *) v_dst, (width + 1) / 2,
                width, height
        );

        env->ReleaseByteArrayElements(src_y, y_src, 0);
        env->ReleaseByteArrayElements(dst_y, y_dst, 0);
        env->ReleaseByteArrayElements(dst_u, u_dst, 0);
        env->ReleaseByteArrayElements(dst_v, v_dst, 0);
    }

    JNIEXPORT void JNICALL
    Java_com_andova_libyuv_LibYUV_00024Companion_TestHalfMergeUVPlane(JNIEnv *env, jobject,
                                                                      jbyteArray src_u, jbyteArray src_v, jbyteArray dst_uv,
                                                                      jint width, jint height) {
        jbyte *u_src = env->GetByteArrayElements(src_u, nullptr);
        jbyte *v_src = env->GetByteArrayElements(src_v, nullptr);
        jbyte *uv_dst = env->GetByteArrayElements(dst_uv, nullptr);

        int halfwidth = (width + 1) / 2;
        int halfheight = (height + 1) / 2;
        libyuv::HalfMergeUVPlane(
                (const uint8_t *) u_src, halfwidth,
                (const uint8_t *) v_src, halfwidth,
                (uint8_t *) uv_dst, halfwidth,
                halfwidth, halfheight);

        env->ReleaseByteArrayElements(src_u, u_src, 0);
        env->ReleaseByteArrayElements(src_v, v_src, 0);
        env->ReleaseByteArrayElements(dst_uv, uv_dst, 0);
    }

#ifdef __cplusplus
    }
}
#endif